
!isEmpty(ROBOTSTUDIO_PRI_INCLUDED):error("Robot_studio.pri already included")
ROBOTSTUDIO_PRI_INCLUDED = 1


# 项目版本号
ROBOTSTUDIO_VERSION = 1.1.0
# 最后一个与此版本兼容的版本号
ROBOTSTUDIO_COMPAT_VERSION = 1.1.0
VERSION = $$ROBOTSTUDIO_VERSION


# 界面中显示的版本号
ROBOTSTUDIO_DISPLAY_VERSION = 1.1.0
# 版权年份信息
ROBOTSTUDIO_COPYRIGHT_YEAR = 2023
# 二进制文件分派的目标分支
BINARY_ARTIFACTS_BRANCH = 1.1


# 标识此IDE的名称
isEmpty(IDE_DISPLAY_NAME):           IDE_DISPLAY_NAME = Robot Studio
isEmpty(IDE_ID):                     IDE_ID = robotstudio
isEmpty(IDE_CASED_ID):               IDE_CASED_ID = RobotStudio


# 使用的C++版本
CONFIG += c++11


# 函数宏 - qtLibraryTargetName-------------------------------
# 对于不同的库，在不同的平台下应该有不同的名称
defineReplace(qtLibraryTargetName) {
   # 清空LIBRARY_NAME变量
   unset(LIBRARY_NAME)
   # 将函数宏的第一个形参赋值给变量LIBRARY_NAME
   LIBRARY_NAME = $$1
   # 当处于Debug模式、或是DebugOrRelease模式下
   CONFIG(debug, debug|release) {
      # 不是同时包含 debug 和 release，或者是编译器的第一遍构建 则
      !debug_and_release|build_pass {
          # mac平台：添加_debug后缀，例如 libfoo_debug
          mac:RET = $$member(LIBRARY_NAME, 0)_debug
              # win32平台: 库名第一个部分后缀加d 例如 "foo.dll" -> "food.dll"
              else:win32:RET = $$member(LIBRARY_NAME, 0)d
      }
   }
   # 如果没有被上述操作设置，就原样返回即可
   isEmpty(RET):RET = $$LIBRARY_NAME

   # 函数返回变量RET
   return($$RET)
}

# 函数宏 - qtLibraryName-------------------------------
# 组合出一个真实库名
defineReplace(qtLibraryName) {
   # 入参宏函数qtLibraryTargetName后返回根据平台的后缀
   RET = $$qtLibraryTargetName($$1)
   # 如果在win32平台下
   win32 {
      # 将版本号用.切开成字符列表 "1.1.0" -> {"1","1","0"}
      VERSION_LIST = $$split(ROBOTSTUDIO_VERSION, .)
      # 将VERSION_LIST列表第一个字符赋给版本号上 "mlib" -> "mlib1"
      RET = $$RET$$first(VERSION_LIST)
   }
   return($$RET)
}


# 函数宏 - minQtVersion-------------------------------
# 用于检查当前 Qt 版本是否大于等于给定的版本号。
defineTest(minQtVersion) {
    # 主版本号
    maj = $$1
    # 次版本号
    min = $$2
    # 修订版本号
    patch = $$3
    # 判断当前 Qt 版本的主版本号是否等于给定版本号的主版本号。
    isEqual(QT_MAJOR_VERSION, $$maj) {
        # 判断当前 Qt 版本的次版本号是否等于给定版本号的次版本号。
        isEqual(QT_MINOR_VERSION, $$min) {
            # 判断当前 Qt 版本的修订版本号是否等于给定版本号的修订版本号。
            isEqual(QT_PATCH_VERSION, $$patch) {
                # 完美的版本配对，返回true
                return(true)
            }
            # 判断当前 Qt 版本的修订版本号是否大于给定版本号的修订版本号。
            greaterThan(QT_PATCH_VERSION, $$patch) {
                return(true)
            }
        }
        # 判断当前 Qt 版本的次版本号是否大于给定版本号的次版本号。
        greaterThan(QT_MINOR_VERSION, $$min) {
            return(true)
        }
    }
    # 判断当前 Qt 版本的主版本号是否大于给定版本号的主版本号。
    greaterThan(QT_MAJOR_VERSION, $$maj) {
        return(true)
    }
    return(false)
}


# 函数宏 - stripSrcDir-------------------------------
# 将参数中的源代码路径转换为相对于当前项目构建目录的路径。
defineReplace(stripSrcDir) {
    # OUT_PWD        指向的是Makefile路径 当前打印实例：F:/ITEM/Robot/build-Robot_studio-Desktop_Qt_5_15_2_MinGW_32_bit-Debug
    # _PRO_FILE_PWD_ 项目文件的根目录     当前打印实例：F:/ITEM/Robot/Robot_studio
    # relative_path() 返回一段路径  是形参二到形参一的相对路径
    return($$relative_path($$absolute_path($$1, $$OUT_PWD), $$_PRO_FILE_PWD_))
}


# 对于可能的McsOS平台的支持
# 如果qt当前版本小于5.7.0且部署的平台是McsOS，则应该把部署目标改为10.8版本的os
# qt默认部署版本为os10.7但是os10.7并不支持全部的C11/C14标准。更改部署设施以支持OS
darwin:!minQtVersion(5, 7, 0) {
    # Qt 5.6 still sets deployment target 10.7, which does not work
    # with all C++11/14 features (e.g. std::future)
    QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.8
}


# 对于测试的配置支持-------------------------------------------------------
# QTC_BUILD_TESTS 变量的值被传递给自己，这是为了确保该变量已经被定义。
RBT_BUILD_TESTS = $$(RBT_BUILD_TESTS)
!isEmpty(RBT_BUILD_TESTS):TEST = $$RBT_BUILD_TESTS

# 如果RBT_BUILD_TESTS不为空 则TEST将会被置为1
!isEmpty(BUILD_TESTS):TEST = 1

# 如果 TEST 变量为空且处于 debug 模式下。  那么TEST置为1
# 注意：只有单独编译debug模式才执行，DebugAndRelease是不触发的
isEmpty(TEST):CONFIG(debug, debug|release) {
    !debug_and_release|build_pass {
        TEST = 1
    }
}


# 如果IDE_LIBRARY_BASENAME变量非空，则设值为lib
# 这个在qt creater中被用于设置插件前缀_默认情况下，其作为插件库其前缀统一为lib
isEmpty(IDE_LIBRARY_BASENAME) {
    IDE_LIBRARY_BASENAME = lib
}

# 如果TEST变量等于1 则触发以下代码
equals(TEST, 1) {
    # 希望qt提供测试单元的库支持
    QT +=testlib
    DEFINES += WITH_TESTS
}




# 这模块定义了IDE_SOURCE_TREE，IDE_BUILD_TREE 这两个存储 路径 相关的变量----------------------------
# IDE_SOURCE_TREE 是当前目录的路径
IDE_SOURCE_TREE = $$PWD
# IDE_BUILD_TREE未定义，则，
isEmpty(IDE_BUILD_TREE) {
    # _PRO_FILE_PWD_ 项目文件的根目录
    sub_dir = $$_PRO_FILE_PWD_
    # 正则替换，从字符串头部开始替换。 目的是将sub_dir 变量中可能包含的 $$PWD 的部分替换为空字符串
    sub_dir ~= s,^$$re_escape($$PWD),,

    IDE_BUILD_TREE = $$clean_path($$OUT_PWD)
    IDE_BUILD_TREE ~= s,$$re_escape($$sub_dir)$,,
}


# 项目的一些输出路径、其他路径 的 配置————————————————————————————————

IDE_APP_PATH = $$IDE_BUILD_TREE/bin

osx {
    # 设置生成的项目名称为IDE_APP_TARGET
    IDE_APP_TARGET   = "$$IDE_DISPLAY_NAME"

    # 这段代码在macOS系统下，检查IDE_BUILD_TREE路径下是否存在指定名称的应用程序（
    # 即$$IDE_APP_TARGET），如果存在则将IDE_APP_BUNDLE设置为$$IDE_BUILD_TREE，
    # 否则将IDE_APP_BUNDLE设置为$$IDE_APP_PATH/$${IDE_APP_TARGET}.app
    #这个逻辑的作用是用于构建二进制包的情况。在这种情况下，IDE_BUILD_TREE
    #可能指向一个已经存在的Qt Creator应用程序的目录，这个应用程序包含了所有的依赖库和插件。
    #这个判断就是为了检查是否使用已经存在的应用程序来构建，如果是，则不需要额外安装依赖库和插件，
    #而是使用已有的应用程序的库和插件即可。
    # check if IDE_BUILD_TREE is actually an existing Qt Creator.app,
    # for building against a binary package
    exists($$IDE_BUILD_TREE/Contents/MacOS/$$IDE_APP_TARGET): IDE_APP_BUNDLE = $$IDE_BUILD_TREE
    else: IDE_APP_BUNDLE = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app

    # set output path if not set manually
    isEmpty(IDE_OUTPUT_PATH): IDE_OUTPUT_PATH = $$IDE_APP_BUNDLE/Contents

    IDE_LIBRARY_PATH = $$IDE_OUTPUT_PATH/Frameworks   # 库的存放存放路径
    IDE_PLUGIN_PATH  = $$IDE_OUTPUT_PATH/PlugIns      # 插件存放存放路径
    IDE_LIBEXEC_PATH = $$IDE_OUTPUT_PATH/Resources    # 资源文件存放路径
    IDE_DATA_PATH    = $$IDE_OUTPUT_PATH/Resources    # 资源文件存放路径
    IDE_DOC_PATH     = $$IDE_DATA_PATH/doc            # 文档文件存放路径
    IDE_BIN_PATH     = $$IDE_OUTPUT_PATH/MacOS        # 可执行文件的路径
    copydata = 1

    # 生成应用程序时所需要的库和插件的查找路径。在 macOS 上，这些路径应该在应用程序的 Contents 目录下。
    LINK_LIBRARY_PATH = $$IDE_APP_BUNDLE/Contents/Frameworks
    # 同理的插件库查找路径
    LINK_PLUGIN_PATH  = $$IDE_APP_BUNDLE/Contents/PlugIns

    # 这里可以发现，如果不出意外的话，存放操作和读取操作可以写为一个路径，但是为了代码的清晰，设计者仍然将之分开
    # 事实上，库的引入位置和库的引出位置可以不一样
    # 库的查找会去往很多隐式的文件夹
    # 再注意，这里的RBT_PREFIX其实是再Robot_studio.pro中进行赋值，而此pri文件可能晚一步pro中的赋值，是否引发问题？
    INSTALL_LIBRARY_PATH = $$RBT_PREFIX/$${IDE_APP_TARGET}.app/Contents/Frameworks
    INSTALL_PLUGIN_PATH  = $$RBT_PREFIX/$${IDE_APP_TARGET}.app/Contents/PlugIns
    INSTALL_LIBEXEC_PATH = $$RBT_PREFIX/$${IDE_APP_TARGET}.app/Contents/Resources
    INSTALL_DATA_PATH    = $$RBT_PREFIX/$${IDE_APP_TARGET}.app/Contents/Resources
    INSTALL_DOC_PATH     = $$INSTALL_DATA_PATH/doc
    INSTALL_BIN_PATH     = $$RBT_PREFIX/$${IDE_APP_TARGET}.app/Contents/MacOS
    INSTALL_APP_PATH     = $$RBT_PREFIX/
} else {
    # 判断变量是否以vc字符串开头 如果是则vcproj变量被赋值为1
    contains(TEMPLATE, vc.*):vcproj = 1
    IDE_APP_TARGET   = $$IDE_ID

    # 如果为设置IDE_OUTPUT_PATH 则将IDE_BUILD_TREE作为各类文件们输出的基点
    isEmpty(IDE_OUTPUT_PATH): IDE_OUTPUT_PATH = $$IDE_BUILD_TREE

    # 库，查找路径
    IDE_LIBRARY_PATH = $$IDE_OUTPUT_PATH/$$IDE_LIBRARY_BASENAME/$$IDE_ID
    # 插件，查找路径
    IDE_PLUGIN_PATH  = $$IDE_LIBRARY_PATH/plugins
    # 数据查找路径
    IDE_DATA_PATH    = $$IDE_OUTPUT_PATH/share/$$IDE_ID
    IDE_DOC_PATH     = $$IDE_OUTPUT_PATH/share/doc/$$IDE_ID
    IDE_BIN_PATH     = $$IDE_OUTPUT_PATH/bin


    win32: \
        IDE_LIBEXEC_PATH = $$IDE_OUTPUT_PATH/bin
    else: \
        IDE_LIBEXEC_PATH = $$IDE_OUTPUT_PATH/libexec/$$IDE_ID

    # 比较两值是否相同卖不相同则copydata为1
    !isEqual(IDE_SOURCE_TREE, $$IDE_OUTPUT_PATH):copydata = 1


    # 生成应用程序时所需要的库和插件的查找路径。
    LINK_LIBRARY_PATH = $$IDE_BUILD_TREE/$$IDE_LIBRARY_BASENAME/$$IDE_ID
    LINK_PLUGIN_PATH  = $$LINK_LIBRARY_PATH/plugins


    # 以下都是各类文件的查找路径_具体是谁的，请看后缀
    INSTALL_LIBRARY_PATH = $$RBT_PREFIX/$$IDE_LIBRARY_BASENAME/$$IDE_ID
    INSTALL_PLUGIN_PATH  = $$INSTALL_LIBRARY_PATH/plugins

    win32: \
        INSTALL_LIBEXEC_PATH = $$RBT_PREFIX/bin
    else: \
        INSTALL_LIBEXEC_PATH = $$RBT_PREFIX/libexec/$$IDE_ID

    INSTALL_DATA_PATH    = $$RBT_PREFIX/share/$$IDE_ID
    INSTALL_DOC_PATH     = $$RBT_PREFIX/share/doc/$$IDE_ID
    INSTALL_BIN_PATH     = $$RBT_PREFIX/bin
    INSTALL_APP_PATH     = $$RBT_PREFIX/bin
}




# 如果使用的是gcc编译器且不是clang编译器，则将-Wno-noexcept-type选项添加到C++编译器选项中
# -Wno-noexcept-type是gcc中的一个警告选项，用于禁止某些情况下的noexcept类型检查警告。
gcc:!clang: QMAKE_CXXFLAGS += -Wno-noexcept-type


# REL = $$relative_path("/src/", /src/dst) 结果是../
# 如下分别是 可执行文件 怎么找到插件？库？资源文件？文档？
RELATIVE_PLUGIN_PATH =  $$relative_path($$IDE_PLUGIN_PATH, $$IDE_BIN_PATH)
RELATIVE_LIBEXEC_PATH = $$relative_path($$IDE_LIBEXEC_PATH, $$IDE_BIN_PATH)
RELATIVE_DATA_PATH =    $$relative_path($$IDE_DATA_PATH, $$IDE_BIN_PATH)
RELATIVE_DOC_PATH =     $$relative_path($$IDE_DOC_PATH, $$IDE_BIN_PATH)
# shell_quote 函数是为了在定义中引用空格或其他特殊字符时，能够正确地进行转义。
# 其本质上都是将路径配置进宏
DEFINES += $$shell_quote(RELATIVE_PLUGIN_PATH=\"$$RELATIVE_PLUGIN_PATH\")
DEFINES += $$shell_quote(RELATIVE_LIBEXEC_PATH=\"$$RELATIVE_LIBEXEC_PATH\")
DEFINES += $$shell_quote(RELATIVE_DATA_PATH=\"$$RELATIVE_DATA_PATH\")
DEFINES += $$shell_quote(RELATIVE_DOC_PATH=\"$$RELATIVE_DOC_PATH\")





INCLUDEPATH += \
#    $$IDE_BUILD_TREE/src \      # for <app/app_version.h> in case of actual build directory
#    $$IDE_SOURCE_TREE/src \     # for <app/app_version.h> in case of binary package with dev package
#    $$IDE_SOURCE_TREE/src/libs/ \



win32:exists($$IDE_SOURCE_TREE/lib/$$IDE_ID) {
    # for .lib in case of binary package with dev package
    LIBS *= -L$$IDE_SOURCE_TREE/lib/$$IDE_ID
    LIBS *= -L$$IDE_SOURCE_TREE/lib/$$IDE_ID/plugins
}



# 插件列表
RBT_PLUGIN_DIRS_FROM_ENVIRONMENT = $$(RBT_PLUGIN_DIRS)
RBT_PLUGIN_DIRS += $$split(RBT_PLUGIN_DIRS_FROM_ENVIRONMENT, $$QMAKE_DIRLIST_SEP)
RBT_PLUGIN_DIRS += $$IDE_SOURCE_TREE/src/plugins


for(dir, RBT_PLUGIN_DIRS) {
    INCLUDEPATH += $$dir
}


CONFIG += \
    depend_includepath \
    no_include_pwd


# 使得当前添加此pri的模块 拥有前面配置的本工程的库文件导出路径
LIBS *= -L$$LINK_LIBRARY_PATH  # Qt Creator libraries
exists($$IDE_LIBRARY_PATH): LIBS *= -L$$IDE_LIBRARY_PATH  # library path from output pat
!isEmpty(vcproj) {
    DEFINES += IDE_LIBRARY_BASENAME=\"$$IDE_LIBRARY_BASENAME\"
} else {
    DEFINES += IDE_LIBRARY_BASENAME=\\\"$$IDE_LIBRARY_BASENAME\\\"
}


DEFINES += \
    QT_CREATOR \
    QT_NO_CAST_TO_ASCII \
    QT_RESTRICTED_CAST_FROM_ASCII \
    QT_DISABLE_DEPRECATED_BEFORE=0x050600 \
    QT_USE_FAST_OPERATOR_PLUS \
    QT_USE_FAST_CONCATENATION


# 如果这是一个qt工程，将会引入一些qt核心库
qt {
    contains(QT, core): QT += concurrent
    contains(QT, gui): QT += widgets
}

# QBS相关 不了解具体问题 似乎也是在告知在何处查找项目的库文件
QBSFILE = $$replace(_PRO_FILE_, \\.pro$, .qbs)
exists($$QBSFILE):DISTFILES += $$QBSFILE

!isEmpty(RBT_PLUGIN_DEPENDS) {
    LIBS *= -L$$IDE_PLUGIN_PATH  # plugin path from output directory
    LIBS *= -L$$LINK_PLUGIN_PATH  # when output path is different from Qt Creator build directory
}


#
# recursively resolve plugin deps

# 核心代码
# 此模块将 去自动的引用工程中 遵循此文件管理方式的插件
# 可以知道，如果一个模块遵循此架构配置，它将会有一个固定的库的导出路径 固定的其他库引入路径
# 正是因为大家都有相同的配置 使得这个代码块能发生效用
done_plugins =
for(ever) {
    # RBT_PLUGIN_DEPENDS 是一个列表 其保存了一系列库名
    # 通过遍历行为 目标动态链接库将会被引入
    isEmpty(RBT_PLUGIN_DEPENDS): \
        break()
    done_plugins += $$RBT_PLUGIN_DEPENDS
    for(dep, RBT_PLUGIN_DEPENDS) {
        dependencies_file =
        for(dir, RBT_PLUGIN_DIRS) {
            exists($$dir/$$dep/$${dep}_dependencies.pri) {
                dependencies_file = $$dir/$$dep/$${dep}_dependencies.pri
                break()
            }
        }
        isEmpty(dependencies_file): \
            error("Plugin dependency $$dep not found")
        include($$dependencies_file)
        # 就是在这被引入的
        LIBS += -l$$qtLibraryName($$RBT_PLUGIN_NAME)
    }
    RBT_PLUGIN_DEPENDS = $$unique(RBT_PLUGIN_DEPENDS)
    RBT_PLUGIN_DEPENDS -= $$unique(done_plugins)
}


# 本质库和插件没什么不同的  如下是库的引入 上下两段代码是在做一件事
# recursively resolve library deps
done_libs =
for(ever) {
    isEmpty(RBT_LIB_DEPENDS): \
        break()
    done_libs += $$RBT_LIB_DEPENDS
    for(dep, RBT_LIB_DEPENDS) {
        include($$PWD/src/libs/$$dep/$${dep}_dependencies.pri)
        LIBS += -l$$qtLibraryName($$RBT_LIB_NAME)
    }
    RBT_LIB_DEPENDS = $$unique(RBT_LIB_DEPENDS)
    RBT_LIB_DEPENDS -= $$unique(done_libs)
}


# 把QTCREATOR_PATH_INFO这个参数 改成1 你就能看到工程中项目的文件路径配置
ROBOT_PATH_INFO = 0
equals(ROBOT_PATH_INFO, 1) {
message("=================PATH info =============================")
message("IDE_LIBRARY_PATH:       " $$IDE_LIBRARY_PATH)
message("IDE_PLUGIN_PATH:        " $$IDE_PLUGIN_PATH)
message("IDE_DATA_PATH:          " $$IDE_DATA_PATH)
message("IDE_DOC_PATH:           " $$IDE_DOC_PATH)
message("IDE_BIN_PATH:           " $$IDE_BIN_PATH)
message("IDE_LIBEXEC_PATH:       " $$IDE_LIBEXEC_PATH)
message("LINK_LIBRARY_PATH:      " $$LINK_LIBRARY_PATH)
message("LINK_PLUGIN_PATH:       " $$LINK_PLUGIN_PATH)
message("INSTALL_LIBRARY_PATH:   " $$INSTALL_LIBRARY_PATH)
message("INSTALL_PLUGIN_PATH:    " $$INSTALL_PLUGIN_PATH)
message("INSTALL_LIBEXEC_PATH:   " $$INSTALL_LIBEXEC_PATH)
message("INSTALL_BIN_PATH:       " $$INSTALL_BIN_PATH)
message("INSTALL_APP_PATH:       " $$INSTALL_APP_PATH)
message("========================================================")
}


